package krao.parser;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.regex.Matcher;

import krao.data.Atom;
import krao.data.ClassAtom;
import krao.data.ConjQuery;
import krao.data.RoleAtom;
import krao.data.UnionConjQuery;

public class ConjQueryParser extends AtomParser {
	public static UnionConjQuery parseQueryFromFile(final String fileName)
			throws FileNotFoundException {
		BufferedReader br = new BufferedReader(new FileReader(fileName));

		UnionConjQuery ucq = new UnionConjQuery();
		String line;
		try {
			while ((line = br.readLine()) != null) {
				logger.trace(line);
				if (!line.startsWith("#") && !line.equals("")) {
					ucq.addQuery(parseQuery(line));
				}
			}
		} catch (IOException e) {
			logger.error(e.getMessage());
		} catch (InvalidQueryException e) {
			logger.error(e.getMessage());
		}
		return ucq;
	}

	/**
	 * Parses the query text into a new Conjunctive Query
	 * 
	 * @param queryText
	 *            text to be parsed
	 * @return new conj. query parsed from the supplied text
	 * @throws InvalidQueryException
	 *             if the supplied text does not match regexp for conj. queries,
	 *             this exception is thrown
	 */
	public static ConjQuery parseQuery(String queryText) throws InvalidQueryException {
		// remove any whitespace
		queryText = queryText.replaceAll("\\s", "");

		if (!queryPattern.matcher(queryText).matches()) {
			throw new InvalidQueryException(
					"Invalid query supplied.\nSupported query form: q(x):-A(x),P(x,y),P(x,Trololo)\n(x and y are variables, Trololo is object)");
		}

		ConjQuery cq = new ConjQuery();
		String[] queryParty = queryText.split(":-");
		// get head
		cq.setHead(parseAtom(queryParty[0]));
		// get body
		String[] atomTexts = queryParty[1].split("\\),");
		for (String atomText : atomTexts) {
			logger.debug(atomText.toString());
			Atom a = parseAtom(atomText);
			logger.debug(a.toString());
			cq.addBodyAtom(a);
		}

		return cq;
	}

	private static Atom parseAtom(String atomText) {
		Matcher roleMatcher = rolePattern.matcher(atomText);
		if (roleMatcher.matches()) {
			RoleAtom ra = new RoleAtom(roleMatcher.group(1), roleMatcher.group(2),
					roleMatcher.group(3));
			return ra;
		} else {
			Matcher classMatcher = classPattern.matcher(atomText);
			if (classMatcher.matches()) {
				ClassAtom ca = new ClassAtom(classMatcher.group(1), classMatcher.group(2));
				return ca;
			}
		}
		return null;
	}
}
